package com.yuexiang.melodyhub.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuexiang.melodyhub.common.constant.UsualConstant.BizCodeConstant;
import com.yuexiang.melodyhub.common.constant.UsualConstant.BizConstant;
import com.yuexiang.melodyhub.common.constant.user.UserStatus;
import com.yuexiang.melodyhub.common.dto.user.UserAdd.param.UserAddParam;
import com.yuexiang.melodyhub.common.dto.user.UserFindByEmail.param.UserFindByEmailParam;
import com.yuexiang.melodyhub.common.dto.user.UserFindByEmail.response.UserFindByEmailResponse;
import com.yuexiang.melodyhub.common.dto.user.UserFindWithRolesByUsername.param.UserFindWithRolesByUsernameParam;
import com.yuexiang.melodyhub.common.dto.user.UserFindWithRolesByUsername.response.UserFindWithRolesByUsernameResponse;
import com.yuexiang.melodyhub.common.exception.RequestArgumentException;
import com.yuexiang.melodyhub.common.utils.PasswordUtil;
import com.yuexiang.melodyhub.user.dao.ProfilesDao;
import com.yuexiang.melodyhub.user.dao.UserDao;
import com.yuexiang.melodyhub.user.dao.UserRoleDao;
import com.yuexiang.melodyhub.user.dto.UserChangeUserStatusByUserId.UserChangeUserStatusByUserIdParam;
import com.yuexiang.melodyhub.user.dto.UserDeleteUserByUserId.param.UserDeleteUserByUserIdParam;
import com.yuexiang.melodyhub.user.dto.UserGetBasicInfos.response.UserGetBasicInfosResponse;
import com.yuexiang.melodyhub.user.dto.UserUpdatePassword.param.UserUpdatePasswordParam;
import com.yuexiang.melodyhub.user.dto.UserUpdateUserInfos.param.UserUpdateUserInfosParam;
import com.yuexiang.melodyhub.user.entity.ProfilesEntity;
import com.yuexiang.melodyhub.user.entity.UserEntity;
import com.yuexiang.melodyhub.user.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;

@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private UserRoleDao userRoleDao;

    @Autowired
    private ProfilesDao profilesDao;

    @Override
    public void add(UserAddParam userParam) {
        this.save(new UserEntity(null, userParam.getEmail(), userParam.getEmail(), PasswordUtil.hashPassword(userParam.getPassword()), null, UserStatus.STATUS_PENDING.getStatus(), new Date(), null));

    }

    @Override
    public UserFindWithRolesByUsernameResponse findWithRolesByUsername(UserFindWithRolesByUsernameParam userFindWithRolesByUsernameParam) {
        UserFindWithRolesByUsernameResponse userFindWithRolesByUsernameResponse = this.baseMapper.findWithRolesByUsername(userFindWithRolesByUsernameParam.getUsername());
        if (userFindWithRolesByUsernameResponse == null || !PasswordUtil.checkPassword(userFindWithRolesByUsernameParam.getPassword(), userFindWithRolesByUsernameResponse.getPassword()))
            return null;
        userFindWithRolesByUsernameResponse.setPassword("*********");
        return userFindWithRolesByUsernameResponse;
    }

    @Override
    public UserFindByEmailResponse findByEmail(UserFindByEmailParam userFindByEmailParam) {
        UserEntity userEntity = this.baseMapper.selectOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getEmail, userFindByEmailParam.getEmail()).or().eq(UserEntity::getUsername, userFindByEmailParam.getEmail()));
        if (userEntity != null) {
            UserFindByEmailResponse userFindByEmailResponse = new UserFindByEmailResponse();
            BeanUtils.copyProperties(userEntity, userFindByEmailResponse);
            userFindByEmailResponse.setPasswordHash("*********");
            return userFindByEmailResponse;
        }
        return null;

    }

    @Override
    public void saveLastTimeByEmail(String email) {
        this.baseMapper.update(null, new LambdaUpdateWrapper<UserEntity>().eq(UserEntity::getEmail, email).set(UserEntity::getLastLogin, new Date()));
    }

    @Override
    public void changeUserStatusByUserId(UserChangeUserStatusByUserIdParam param) {
    }

    @Override
    public void deleteUserByUserId(UserDeleteUserByUserIdParam param) {
    }

    @Override
    public UserGetBasicInfosResponse getBasicInfos(String email) {
        return this.baseMapper.getBasicInfos(email);
    }

    @Transactional
    @Override
    public void updateUserInfos(UserUpdateUserInfosParam param) {
        // 验证用户名
        UserEntity userEntity = this.baseMapper.selectOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUsername, param.getUsername()));
        if (!StringUtils.hasLength(param.getUsername()) || (userEntity != null && !userEntity.getUsername().equals(param.getUsername())))
            throw new RequestArgumentException(BizCodeConstant.Msg.U_NAME_IS_EXIST);
        // 更新用户信息
        this.baseMapper.update(null, new LambdaUpdateWrapper<UserEntity>().eq(UserEntity::getEmail, param.getEmail())
                .set(UserEntity::getUsername, param.getUsername())
                .set(UserEntity::getAvatar, param.getAvatar()));

        profilesDao.update(null, new LambdaUpdateWrapper<ProfilesEntity>().eq(ProfilesEntity::getUserId, param.getUserId())
                .set(ProfilesEntity::getGender, param.getGender())
                .set(ProfilesEntity::getBirthdate, param.getBirthdate())
                .set(ProfilesEntity::getBio, param.getBio())
                .set(ProfilesEntity::getRegion, param.getRegion())
                .set(ProfilesEntity::getMusicLink, param.getMusicLink())
                .set(ProfilesEntity::getSocialMedia, param.getSocialMedia()));
    }

    @Override
    public void updatePassword(UserUpdatePasswordParam param) {
        UserEntity userEntity = this.baseMapper.selectOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getEmail, param.getEmail()));
        // 判断旧密码是否正确
        if (!PasswordUtil.checkPassword(param.getOldPassword(), userEntity.getPasswordHash()))
            throw new RequestArgumentException(BizCodeConstant.Msg.OLD_PASS_IS_INCORRECT);
        // 判断新密码是否 一致、合法
        if (!param.getNewPassword().equals(param.getConfirmPassword()))
            throw new RequestArgumentException(BizCodeConstant.Msg.REPEAT_PASSWORD_IS_INVALID);
        if (!PasswordUtil.validatePassword(param.getNewPassword()))
            throw new RequestArgumentException(BizCodeConstant.Msg.PASSWORD_IS_INVALID);
        // 提交修改 删除token
        this.baseMapper.update(null, new LambdaUpdateWrapper<UserEntity>().eq(UserEntity::getEmail, param.getEmail())
                .set(UserEntity::getPasswordHash, PasswordUtil.hashPassword(param.getNewPassword()))
                .set(UserEntity::getLastLogin, new Date()));
        removeUserToken(userEntity.getUsername());
    }

    public void removeUserToken(String username) {
        redisTemplate.delete(BizConstant.TOKEN_CACHE_PREFIX + username);
    }
}
